<template>
  <div class="disk-container">
    <el-card>
      <template #header>
        <div class="card-header">
          <span>知识笔记</span>
          <div class="header-actions">
            <el-radio-group v-model="currentView" size="small" @change="handleViewChange">
              <el-radio-button label="personal">个人文件</el-radio-button>
              <el-radio-button label="shared">共享文件</el-radio-button>
              <el-radio-button label="trash">回收站</el-radio-button>
            </el-radio-group>
            <el-button
              v-if="currentView !== 'trash'"
              type="primary"
              :icon="Plus"
              @click="handleNewNote"
            >
              新建笔记
            </el-button>
          </div>
        </div>
      </template>

      <div class="header-filter">
        <el-form :model="queryForm" ref="queryFormRef" :inline="true" label-width="80px">
          <el-form-item label="关键词">
            <el-input
              v-model="queryForm.keywords"
              placeholder="请输入笔记标题或内容"
              clearable
              @keyup.enter="handleSearch"
            />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="handleSearch">搜索</el-button>
            <el-button @click="handleReset">重置</el-button>
          </el-form-item>
        </el-form>
      </div>
    </el-card>

    <el-card class="note-content">
      <div class="file-grid">
        <div v-for="note in noteList" :key="note.id" class="note-item">
          <div class="note-info" @click="handleNoteClick(note)">
            <div class="note-title" :title="note.title || note.name">
              {{ note.title || note.name }}
            </div>
            <div class="note-preview" :title="getPreviewContent(note.content)">
              {{ getPreviewContent(note.content) }}
            </div>
            <div class="note-meta">
              <span>{{ formatDate(note.create_time) }}</span>
              <span v-if="note.author">创建者: {{ note.author }}</span>
              <span v-if="note.attachment_count > 0">附件: {{ note.attachment_count }}</span>
            </div>
          </div>
          <div class="file-actions">
            <el-dropdown @command="handleCommand" trigger="click" placement="bottom">
              <el-button size="small" circle>
                <el-icon><More /></el-icon>
              </el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item :command="{ action: 'edit', id: note.id }">
                    编辑
                  </el-dropdown-item>
                  <el-dropdown-item
                    :command="{ action: 'share', id: note.id }"
                    v-if="!note.status || note.status === 0"
                  >
                    分享
                  </el-dropdown-item>
                  <el-dropdown-item
                    :command="{ action: 'unshare', id: note.id }"
                    v-if="note.status === 1"
                  >
                    取消分享
                  </el-dropdown-item>
                  <el-dropdown-item
                    :command="{ action: 'delete', id: note.id }"
                    divided
                    type="danger"
                  >
                    删除
                  </el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
          <div v-if="note.status === 1" class="share-badge">
            <el-icon><Share /></el-icon>
          </div>
        </div>

        <div v-if="loading" class="loading-container">
          <el-skeleton :rows="12" animated />
        </div>

        <div v-if="!loading && noteList.length === 0" class="empty-container">
          <el-empty description="暂无笔记" />
        </div>
      </div>

      <div class="pagination-container">
        <el-pagination
          v-model:current-page="queryForm.page"
          v-model:page-size="queryForm.limit"
          :page-sizes="[10, 20, 50, 100]"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </el-card>

    <!-- 新建/编辑笔记抽屉 -->
    <GlobalDrawer
      v-model="noteDrawerVisible"
      :title="isEditMode ? '编辑笔记' : '新增笔记'"
      size="80%"
      @confirm="handleSaveNote"
    >
      <el-form :model="noteForm" :rules="noteRules" ref="noteFormRef" label-width="80px">
        <el-form-item label="笔记标题" prop="name">
          <el-input v-model="noteForm.name" placeholder="请输入笔记标题" />
        </el-form-item>
        <el-form-item label="笔记内容">
          <!-- 富文本编辑器 -->
          <div class="rich-text-editor">
            <div class="editor-toolbar">
              <el-button size="small" @click="formatText('bold')" title="粗体">
                <strong>B</strong>
              </el-button>
              <el-button size="small" @click="formatText('italic')" title="斜体">
                <em>I</em>
              </el-button>
              <el-button size="small" @click="formatText('underline')" title="下划线">
                <u>U</u>
              </el-button>
              <el-divider direction="vertical" />
              <el-button size="small" @click="formatText('heading1')" title="标题1">H1</el-button>
              <el-button size="small" @click="formatText('heading2')" title="标题2">H2</el-button>
              <el-button size="small" @click="formatText('heading3')" title="标题3">H3</el-button>
              <el-divider direction="vertical" />
              <el-button size="small" @click="formatText('listBullet')" title="无序列表">
                <el-icon><List /></el-icon>
              </el-button>
              <el-button size="small" @click="formatText('listOrdered')" title="有序列表">
                <el-icon><MoreFilled /></el-icon>
              </el-button>
              <el-divider direction="vertical" />
            </div>
            <div
              ref="editorRef"
              contenteditable="true"
              class="content-editor"
              @input="handleEditorInput"
              @blur="handleEditorBlur"
              @focus="handleEditorFocus"
            ></div>
          </div>
        </el-form-item>

        <el-form-item label="附件上传">
          <el-upload
            :http-request="customUpload"
            :file-list="uploadForm.fileList"
            :before-upload="beforeUpload"
            :on-remove="handleFileRemove"
            :on-success="handleFileUploadSuccess"
            :auto-upload="true"
            :with-credentials="true"
            multiple
            :limit="5"
            :show-file-list="true"
            :drag="false"
            :name="'file'"
            accept=".pdf,.doc,.docx,.xls,.xlsx,.txt,.jpg,.jpeg,.png,.gif"
          >
            <el-button type="primary" size="small">
              <el-icon><Upload /></el-icon>
              选择文件
            </el-button>
            <template #tip>
              <div class="el-upload__tip">
                支持PDF、Word、Excel等格式，单个文件不超过10MB，最多上传5个文件
              </div>
            </template>
          </el-upload>
        </el-form-item>
      </el-form>
    </GlobalDrawer>

    <!-- 分享对话框 -->
    <el-dialog v-model="shareDialogVisible" title="分享笔记" width="50%">
      <el-form :model="shareForm" ref="shareFormRef" label-width="100px">
        <el-form-item label="分享对象类型">
          <el-radio-group v-model="shareForm.shareType">
            <el-radio :label="1">个人</el-radio>
            <el-radio :label="2">部门</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="选择对象">
          <el-select
            v-model="shareForm.targetIds"
            placeholder="请选择分享对象"
            multiple
            collapse-tags
            :loading="loadingShareOptions"
            :disabled="loadingShareOptions"
          >
            <template #prefix>
              <el-icon v-if="loadingShareOptions"><Refresh /></el-icon>
            </template>
            <el-option
              v-for="option in getShareOptions()"
              :key="option.value"
              :label="option.label"
              :value="option.value"
            />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="shareDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleShareSubmit" :loading="loadingShareOptions">
            确认分享
          </el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 查看笔记抽屉 -->
    <GlobalDrawer
      v-model="viewDialogVisible"
      :title="'查看 - ' + (currentNote?.title || currentNote?.name || '')"
      size="80%"
    >
      <div class="view-note-meta">
        <span>创建时间: {{ currentNote ? formatDate(currentNote.create_time) : '' }}</span>
        <span v-if="currentNote?.author">创建者: {{ currentNote.author }}</span>
        <span v-if="currentNote?.attachment_count > 0">
          附件: {{ currentNote.attachment_count }}
        </span>
      </div>
      <div class="view-note-content" v-html="currentNote?.content || ''"></div>

      <!-- 附件列表 -->
      <div
        v-if="currentNote?.attachments && currentNote.attachments.length > 0"
        class="view-note-attachments"
      >
        <h4>附件</h4>
        <ul>
          <li v-for="(attachment, index) in currentNote.attachments" :key="index">
            <el-button type="text" @click="handleDownloadAttachment(attachment)">
              <el-icon><Document /></el-icon>
              {{ attachment.name || attachment.filename || '未命名文件' }}
            </el-button>
            <el-button
              v-if="isPreviewable(attachment)"
              type="text"
              size="small"
              @click="handleFilePreview(attachment)"
            >
              <el-icon><View /></el-icon>
              预览
            </el-button>
          </li>
        </ul>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="viewDialogVisible = false">关闭</el-button>
          <el-button type="primary" @click="handleEditNote(currentNote)">编辑</el-button>
        </div>
      </template>
    </GlobalDrawer>

    <!-- 文件预览对话框 -->
    <el-dialog
      v-model="previewVisible"
      :title="
        previewFile ? `预览 - ${previewFile.name || previewFile.filename || '文件'}` : '文件预览'
      "
      width="80%"
      destroy-on-close
      @closed="handlePreviewClosed"
    >
      <div v-loading="previewLoading" class="preview-container">
        <!-- PDF预览 -->
        <div
          v-if="previewFile && (previewFile.ext === 'pdf' || previewFile.ext === 'PDF')"
          class="pdf-preview"
        >
          <iframe
            v-if="previewUrl"
            :src="previewUrl"
            width="100%"
            height="600px"
            frameborder="0"
            @error="handlePreviewError"
          ></iframe>
        </div>

        <!-- 图片预览 -->
        <div v-else-if="previewFile && isImageFile(previewFile.ext)" class="image-preview">
          <img
            v-if="previewUrl"
            :src="previewUrl"
            :alt="previewFile.name || previewFile.filename || '图片'"
            style="max-width: 100%; max-height: 600px"
            @error="handlePreviewError"
          />
        </div>

        <!-- 文本预览 -->
        <div v-else-if="previewFile && isTextFile(previewFile.ext)" class="text-preview">
          <el-input
            v-model="textPreviewContent"
            type="textarea"
            :rows="20"
            readonly
            placeholder="文件内容为空或无法预览"
          />
        </div>

        <!-- 不支持预览的文件类型 -->
        <div v-else class="no-preview">
          <el-empty description="该文件类型不支持预览，请下载后查看">
            <el-button type="primary" @click="handleDownloadAttachment(previewFile)">
              下载文件
            </el-button>
          </el-empty>
        </div>
      </div>

      <template #footer>
        <span class="dialog-footer">
          <el-button @click="previewVisible = false">关闭</el-button>
          <el-button type="primary" @click="handleDownloadAttachment(previewFile)">下载</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
  import {
    Upload,
    More,
    Share,
    Document,
    EditPen,
    Operation,
    SetUp,
    List,
    MoreFilled,
    Plus,
    Delete,
    Refresh,
    View,
    Loading,
  } from '@element-plus/icons-vue'
  import { ref, reactive, onMounted, nextTick, watch } from 'vue'
  import { ElMessage, ElMessageBox } from 'element-plus'
  import type { UploadFile, UploadFiles } from 'element-plus'
  import GlobalDrawer from '@/components/common/GlobalDrawer.vue'
  import config from '@/config/index'
  import { getPublicFileDetail } from '@/api/home/files'
  import axios from 'axios'
  import type { AxiosResponse } from 'axios'
  import {
    getNoteList,
    getNoteDetail,
    createNote,
    updateNote,
    deleteNote,
    shareNote,
    unshareNote,
    downloadAttachment,
    uploadAttachment,
    removeAttachment,
    getShareableUsers,
    getShareableDepartments,
    restoreNote,
    forceDeleteNote,
    type Note,
  } from '@/services/disk'
  import request from '@/utils/request' // 添加request导入

  // 移除了对 useNoteStore 的引用，因为我们直接使用 API 服务

  // 获取文件URL
  interface Attachment {
    id?: number
    filepath?: string
    file_path?: string
    name?: string
    filename?: string
  }

  const getFileUrl = (attachment: Attachment) => {
    // 获取附件路径
    const filePath = attachment.filepath || attachment.file_path || ''

    // 如果已经是完整URL则直接返回
    if (filePath.startsWith('http://') || filePath.startsWith('https://')) {
      return filePath
    }

    // 否则构建完整URL
    // 使用配置中的API基础URL
    const baseUrl = config.API_BASE_URL || 'http://127.0.0.1:8000'
    // 确保路径拼接时不会有重复的斜杠
    const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl
    const normalizedFilePath = filePath.startsWith('/') ? filePath : `/${filePath}`

    return `${normalizedBaseUrl}${normalizedFilePath}`
  }

  // 处理附件下载
  const handleDownloadAttachment = async (attachment: Attachment) => {
    // 创建变量用于存储需要清理的资源
    let url: string | null = null
    let link: HTMLAnchorElement | null = null

    try {
      // 文件名优先级：name > filename > '未命名文件'
      const fileName = attachment.name || attachment.filename || '未命名文件'

      // 基本参数验证
      if (!attachment || !attachment.id || !fileName) {
        ElMessage.error('下载参数无效')
        return
      }

      ElMessage.info(`准备下载文件: ${fileName}`)

      // 调用下载附件API获取文件数据
      const blob = await downloadAttachment(attachment.id)

      // 执行文件下载
      url = window.URL.createObjectURL(blob)
      link = document.createElement('a')
      link.href = url
      link.download = fileName
      link.style.display = 'none'
      document.body.appendChild(link)
      link.click()

      ElMessage.success(`文件下载成功: ${fileName}`)
    } catch (error: any) {
      // 特殊处理令牌无效或已过期的错误
      if (error.message && (error.message.includes('令牌无效') || error.message.includes('401'))) {
        ElMessage.error('登录已过期，请重新登录后再尝试下载')
      } else {
        const errorMsg = error.message || '下载附件失败，请重试'
        ElMessage.error(errorMsg)
      }
    } finally {
      // 清理临时对象
      if (link && document.body.contains(link)) {
        document.body.removeChild(link)
      }
      if (url) {
        // 使用setTimeout确保浏览器有时间完成下载
        setTimeout(() => {
          if (url) {
            window.URL.revokeObjectURL(url)
          }
        }, 100)
      }
    }
  }

  // 查询表单
  const queryForm = reactive({
    page: 1,
    limit: 10,
    keywords: '',
    status: 0, // 0: 个人文件, 1: 共享文件, -1: 回收站
  })

  // 笔记表单接口
  type NoteForm = {
    id: number
    name: string
    content: string
    status: number // 状态字段，0表示未分享，1表示已分享
  }

  // 上传表单
  const uploadForm = reactive({
    fileList: [] as any[],
  })

  // 笔记表单
  const noteForm = reactive<NoteForm>({
    id: 0,
    name: '',
    content: '',
    status: 0, // 默认未分享
  })

  // 数据相关
  const noteList = ref<any[]>([])
  const total = ref(0)
  const loading = ref(false)
  const isEditMode = ref(false)
  const currentNote = ref<any>(null)
  const viewDialogVisible = ref(false)

  // 对话框相关
  const noteDrawerVisible = ref(false)
  const shareDialogVisible = ref(false)

  // 表单引用
  const noteFormRef = ref()
  const queryFormRef = ref()
  const shareFormRef = ref()
  const editorRef = ref<HTMLDivElement | null>(null)

  // 真实分享选项数据
  const userOptions = ref<Array<{ value: number; label: string }>>([])
  const departmentOptions = ref<Array<{ value: number; label: string }>>([])
  const loadingShareOptions = ref(false)

  // 加载分享选项数据
  const loadShareOptions = async () => {
    loadingShareOptions.value = true
    try {
      // 并行请求获取可分享的用户和部门列表
      const [usersRes, departmentsRes] = await Promise.all([
        getShareableUsers(),
        getShareableDepartments(),
      ])

      // 处理用户数据
      if (usersRes.code === 0 && Array.isArray(usersRes.data)) {
        userOptions.value = usersRes.data.map(user => ({
          value: user.id,
          label: user.name,
        }))
      } else {
        console.warn('获取可分享用户列表失败:', usersRes.msg)
      }

      // 处理部门数据
      if (departmentsRes.code === 0 && Array.isArray(departmentsRes.data)) {
        departmentOptions.value = departmentsRes.data
          .map((dept: any) => ({
            value: dept.id || (dept as any).department_id || 0,
            label: dept.name || (dept as any).department_name || (dept as any).title || '未知部门',
          }))
          .filter(dept => dept.value > 0) // 过滤无效数据
      } else {
        console.warn('获取可分享部门列表失败:', departmentsRes.msg || '未知错误')
      }
    } catch (error) {
      console.error('加载分享选项失败:', error)
      ElMessage.error('加载分享选项失败，请刷新页面重试')
    } finally {
      loadingShareOptions.value = false
    }
  }

  // 获取分享选项
  const getShareOptions = () => {
    return shareForm.shareType === 1 ? userOptions.value : departmentOptions.value
  }

  // 格式化日期
  const formatDate = (date: string): string => {
    const d = new Date(date)
    return d.toLocaleString('zh-CN')
  }

  // 获取预览内容
  const getPreviewContent = (content: string): string => {
    // 检查content是否为空或未定义
    if (!content || typeof content !== 'string') {
      return ''
    }
    // 移除HTML标签并截取前50个字符
    const plainText = content.replace(/<[^>]*>/g, '')
    return plainText.length > 50 ? plainText.substring(0, 50) + '...' : plainText
  }

  // 获取笔记列表
  const fetchNoteList = async () => {
    loading.value = true
    try {
      const params = {
        page: queryForm.page,
        limit: queryForm.limit,
        keywords: queryForm.keywords,
      }

      // 调用笔记相关的API
      const res = await getNoteList(params)

      if (res.code === 0) {
        // 确保正确处理分页数据结构
        if (res.data && Array.isArray(res.data.list)) {
          noteList.value = res.data.list
          total.value = res.data.total || 0
        } else if (Array.isArray(res.data)) {
          // 兼容旧的数据结构
          noteList.value = res.data
          total.value = res.count || 0
        } else {
          noteList.value = []
          total.value = 0
        }
      } else {
        ElMessage.error(res.msg || '获取笔记列表失败')
        noteList.value = []
        total.value = 0
      }
    } catch (error) {
      ElMessage.error('获取笔记列表失败: ' + (error as Error).message)
      noteList.value = []
      total.value = 0
    } finally {
      loading.value = false
    }
  }

  // 搜索
  const handleSearch = () => {
    queryForm.page = 1
    fetchNoteList()
  }

  // 重置
  const handleReset = () => {
    Object.assign(queryForm, {
      keywords: '',
      page: 1,
    })
    fetchNoteList()
  }

  // 监听抽屉可见性变化，确保编辑器正确初始化
  watch(noteDrawerVisible, newVal => {
    if (newVal) {
      nextTick(() => {
        if (editorRef.value) {
          if (isEditMode.value) {
            editorRef.value.innerHTML = noteForm.content || ''
          } else {
            editorRef.value.innerHTML = ''
          }
        }
      })
    }
  })

  // 新建笔记
  const handleNewNote = () => {
    isEditMode.value = false
    noteForm.id = 0
    noteForm.name = ''
    noteForm.content = ''
    // 清空上传状态
    uploadForm.fileList = []
    noteDrawerVisible.value = true
  }

  // 编辑笔记
  const handleEditNote = (note: any) => {
    isEditMode.value = true
    noteForm.id = note.id
    noteForm.name = note.title || note.name || ''
    noteForm.content = note.content || ''
    // 清空上传状态
    uploadForm.fileList = []

    // 加载已有的附件到el-upload的fileList
    if (note.attachments && Array.isArray(note.attachments) && note.attachments.length > 0) {
      uploadForm.fileList = note.attachments.map((attachment: any) => ({
        name: attachment.name || attachment.filename || '未命名文件',
        size: attachment.size || attachment.filesize || attachment.file_size || 0,
        url: attachment.filepath || attachment.file_path || '',
        // 标记为已上传的文件
        status: 'success',
        // 存储实际的文件ID
        response: {
          data: {
            id: attachment.id || attachment.file_id || attachment.upload_file_id,
          },
        },
      }))
      console.log('加载已有附件:', uploadForm.fileList)
    }

    noteDrawerVisible.value = true
  }

  // 查看笔记详情
  const handleNoteClick = (note: any) => {
    // 使用fetchNoteDetail获取最新的笔记详情
    fetchNoteDetail(note.id)
    viewDialogVisible.value = true
  }

  // 获取笔记详情
  const fetchNoteDetail = async (id: number) => {
    try {
      const res = await getNoteDetail(id)
      if (res.code === 0) {
        currentNote.value = res.data
      } else {
        ElMessage.error(res.msg || '获取笔记详情失败')
      }
    } catch (error) {
      ElMessage.error('获取笔记详情失败: ' + (error as Error).message)
    }
  }

  // 处理命令操作
  const handleCommand = (command: { action: string; id: number }) => {
    const note = noteList.value.find(n => n.id === command.id)
    if (!note) return

    switch (command.action) {
      case 'edit':
        handleEditNote(note)
        break
      case 'share':
        handleShareNote(note)
        break
      case 'unshare':
        handleUnshareNote(note)
        break
      case 'delete':
        handleDeleteNote(note)
        break
      case 'view':
        handleNoteClick(note)
        break
      case 'restore':
        handleRestoreNote(note)
        break
      case 'forceDelete':
        handleForceDeleteNote(note)
        break
    }
  }

  // 分享表单
  const shareForm = reactive({
    noteId: 0,
    shareType: 1,
    targetIds: [] as number[],
  })

  // 分享笔记
  const handleShareNote = async (note: any) => {
    shareForm.noteId = note.id
    shareForm.shareType = 1
    shareForm.targetIds = []

    // 确保分享选项数据已加载
    if (userOptions.value.length === 0 || departmentOptions.value.length === 0) {
      await loadShareOptions()
    }

    shareDialogVisible.value = true
  }

  // 提交分享
  const handleShareSubmit = async () => {
    if (shareForm.targetIds.length === 0) {
      ElMessage.warning('请选择分享对象')
      return
    }

    try {
      // 构造符合API要求的参数格式
      const params: { id: number; user_ids?: string; department_ids?: string } = {
        id: shareForm.noteId,
      }

      // 根据分享类型设置对应的参数
      if (shareForm.shareType === 1) {
        // 分享给个人
        params.user_ids = shareForm.targetIds.join(',')
      } else if (shareForm.shareType === 2) {
        // 分享给部门
        params.department_ids = shareForm.targetIds.join(',')
      }

      const res = await shareNote(params)

      if (res.code === 0) {
        ElMessage.success('笔记分享成功')
        shareDialogVisible.value = false
        fetchNoteList()
      } else {
        ElMessage.error(res.msg || '笔记分享失败')
      }
    } catch (error) {
      ElMessage.error('笔记分享失败: ' + (error as Error).message)
    }
  }

  // 取消分享
  const handleUnshareNote = async (note: Note) => {
    try {
      ElMessageBox.confirm('确定要取消分享此笔记吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(async () => {
          // 转换为string类型以匹配API要求
          const res = await unshareNote(note.id.toString())

          if (res.code === 0) {
            ElMessage.success('取消分享成功')
            fetchNoteList()
          } else {
            ElMessage.error(res.msg || '取消分享失败')
          }
        })
        .catch(() => {
          // 用户取消操作，无需处理
        })
    } catch (error) {
      ElMessage.error('取消分享失败: ' + (error as Error).message)
    }
  }

  // 删除笔记
  const handleDeleteNote = async (note: Note) => {
    try {
      await ElMessageBox.confirm('确定要删除该笔记吗？删除后将无法恢复', '删除确认', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })

      const res = await deleteNote(note.id)

      if (res.code === 0) {
        ElMessage.success('笔记删除成功')
        fetchNoteList()
      } else {
        ElMessage.error(res.msg || '笔记删除失败')
      }
    } catch (error) {
      // 用户取消删除操作时不提示错误
      if ((error as Error).message !== 'cancel') {
        ElMessage.error('笔记删除失败: ' + (error as Error).message)
      }
    }
  }

  // 调试函数：打印文件ID提取情况
  const debugFileIds = () => {
    const validFiles = uploadForm.fileList.filter(file => {
      const isValid = file.status === 'success' && file.response && file.response.data
      console.log(`文件 ${file.name}:`, {
        status: file.status,
        hasResponse: !!file.response,
        hasData: !!(file.response && file.response.data),
        isValid,
      })
      return isValid
    })

    const fileIds = validFiles
      .map(file => {
        const fileId =
          file.response?.data?.id || file.upload_file_id || file.file_id || file.response?.id
        console.log(
          `文件 ${file.name} 提取的ID:`,
          fileId,
          '来源:',
          file.response?.data?.id
            ? 'response.data.id'
            : file.upload_file_id
              ? 'upload_file_id'
              : file.file_id
                ? 'file_id'
                : file.response?.id
                  ? 'response.id'
                  : '未知'
        )
        return fileId
      })
      .filter(Boolean)

    return fileIds
  }

  // 增强版调试函数：区分新上传文件和已有附件
  const debugAllFileIds = () => {
    const newUploadedFiles: any[] = []
    const existingAttachments: any[] = []

    uploadForm.fileList.forEach((file: any) => {
      // 打印每个文件的完整结构，便于调试

      // 特别打印response对象的详细内容
      if (file.response) {
      }

      // 尝试从多个可能的字段获取ID
      const fileId =
        file.response?.data?.id ||
        file.upload_file_id ||
        file.file_id ||
        file.response?.id ||
        file.id // 添加直接从file对象获取ID的尝试

      const fileInfo = {
        name: file.name,
        id: fileId,
        status: file.status,
        isNewUpload: !!file.uid, // 有uid的是新上传的文件
        hasResponse: !!file.response,
        source: file.response?.data?.id
          ? 'response.data.id'
          : file.upload_file_id
            ? 'upload_file_id'
            : file.file_id
              ? 'file_id'
              : file.response?.id
                ? 'response.id'
                : file.id
                  ? 'file.id'
                  : '未知',
      }

      if (file.uid) {
        newUploadedFiles.push(fileInfo)
      } else {
        existingAttachments.push(fileInfo)
      }
    })

    const allFileIds = [...newUploadedFiles, ...existingAttachments]
      .filter(file => file.id)
      .map(file => file.id)

    return allFileIds
  }

  // 保存笔记
  const noteRules = {
    name: [
      { required: true, message: '请输入笔记标题', trigger: 'blur' },
      { max: 100, message: '笔记标题不能超过100个字符', trigger: 'blur' },
    ],
    // 移除content的required验证，只保留最大长度验证
  }

  const handleSaveNote = async () => {
    // 确保表单验证通过
    const valid = await noteFormRef.value.validate()
    if (!valid) return

    // 确保编辑器内容被更新到noteForm.content
    if (editorRef.value) {
      noteForm.content = editorRef.value.innerHTML
    }

    try {
      // 打印当前文件列表，用于调试
      console.log('保存笔记时的文件列表:', uploadForm.fileList)

      // 打印每个文件的详细信息
      uploadForm.fileList.forEach((file, index) => {
        console.log(`文件${index}:`, {
          name: file.name,
          status: file.status,
          response: file.response,
          uid: file.uid,
        })
      })

      // 调用增强版调试函数查看所有文件ID提取情况
      const allFileIds = debugAllFileIds()

      // 如果有文件但未能提取到ID，打印警告
      if (uploadForm.fileList.length > 0 && allFileIds.length === 0) {
      }

      // 构建提交数据
      const submitData = {
        id: noteForm.id,
        title: noteForm.name, // 将name映射为title
        // 如果内容为空，提供一个默认值，避免后端验证失败
        content: noteForm.content || '<p>暂无内容</p>',
        // 从上传文件列表中提取所有文件ID（包括新上传的和已有的）
        file_ids: allFileIds.join(','),
      }

      // 打印提取的文件ID，用于调试
      console.log('提交的文件ID:', submitData.file_ids)
      console.log('提交的文件ID数量:', allFileIds.length)

      // 调用保存笔记的API
      const res = isEditMode.value ? await updateNote(submitData) : await createNote(submitData)

      if (res.code === 0) {
        ElMessage.success(isEditMode.value ? '笔记更新成功' : '笔记创建成功')
        noteDrawerVisible.value = false
        fetchNoteList()

        // 如果当前正在查看这个笔记，刷新笔记详情
        if (currentNote.value && currentNote.value.id === noteForm.id) {
          fetchNoteDetail(noteForm.id)
        }
      } else {
        ElMessage.error(res.msg || `保存笔记失败，错误码: ${res.code}`)
      }
    } catch (error) {
      // 提供更详细的错误信息
      let errorMessage = '保存笔记失败'
      if (error && typeof error === 'object') {
        const errorObj = error as any
        if (errorObj.message) {
          errorMessage = `保存笔记失败: ${errorObj.message}`
        } else if (errorObj.response && errorObj.response.data && errorObj.response.data.msg) {
          errorMessage = `保存笔记失败: ${errorObj.response.data.msg}`
        } else if (errorObj.response && errorObj.response.status) {
          errorMessage = `保存笔记失败，服务器状态码: ${errorObj.response.status}`
        } else {
          errorMessage = '保存笔记失败: 未知错误'
        }
      } else if (typeof error === 'string') {
        errorMessage = `保存笔记失败: ${error}`
      }
      ElMessage.error(errorMessage)
    }
  }

  // 处理编辑器输入
  const handleEditorInput = () => {
    if (editorRef.value) {
      noteForm.content = editorRef.value.innerHTML
    }
  }

  // 处理编辑器失焦
  const handleEditorBlur = () => {
    if (editorRef.value) {
      noteForm.content = editorRef.value.innerHTML
    }
  }

  // 处理编辑器聚焦
  const handleEditorFocus = () => {
    // 聚焦时的处理逻辑，如需要可以添加
  }

  // 格式化文本
  const formatText = (formatType: string) => {
    // 检查编辑器引用
    if (!editorRef.value) return

    // 获取当前选择范围
    const selection = window.getSelection()
    if (!selection || selection.rangeCount === 0) return

    const range = selection.getRangeAt(0)
    const selectedText = range.toString()

    // 保存当前光标位置的偏移量
    const startOffset = range.startOffset
    const endOffset = range.endOffset

    try {
      // 不同格式类型的处理
      switch (formatType) {
        case 'bold':
          document.execCommand('bold', false, '')
          break
        case 'italic':
          document.execCommand('italic', false, '')
          break
        case 'underline':
          document.execCommand('underline', false, '')
          break
        case 'heading1':
          // 移除当前选中区域的所有格式
          document.execCommand('removeFormat', false, '')
          // 设置为标题1
          document.execCommand('formatBlock', false, 'h1')
          break
        case 'heading2':
          // 移除当前选中区域的所有格式
          document.execCommand('removeFormat', false, '')
          // 设置为标题2
          document.execCommand('formatBlock', false, 'h2')
          break
        case 'heading3':
          // 移除当前选中区域的所有格式
          document.execCommand('removeFormat', false, '')
          // 设置为标题3
          document.execCommand('formatBlock', false, 'h3')
          break
        case 'listBullet':
          document.execCommand('insertUnorderedList', false, '')
          break
        case 'listOrdered':
          document.execCommand('insertOrderedList', false, '')
          break
        default:
          break
      }
    } catch (error) {
      console.error('格式化文本失败:', error)
    } finally {
      // 确保编辑器内容被更新到noteForm.content
      if (editorRef.value) {
        noteForm.content = editorRef.value.innerHTML
      }
    }
  }

  // 处理文件移除
  const handleFileRemove = (file: UploadFile, fileList: UploadFiles) => {
    // 更新uploadForm.fileList - 确保使用最新的fileList
    uploadForm.fileList = [...fileList]
    console.log('移除文件后的列表:', uploadForm.fileList)
  }

  // 上传前检查
  const beforeUpload = (file: File): boolean => {
    const isLt10M = file.size / 1024 / 1024 < 10
    if (!isLt10M) {
      ElMessage.error('上传文件大小不能超过 10MB!')
      return false
    }

    // 检查文件类型
    const fileExtension = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase()
    const allowedExtensions = [
      'pdf',
      'doc',
      'docx',
      'xls',
      'xlsx',
      'txt',
      'jpg',
      'jpeg',
      'png',
      'gif',
    ]

    if (!allowedExtensions.includes(fileExtension)) {
      ElMessage.error('不支持的文件类型，请上传PDF、Word、Excel、文本或图片文件')
      return false
    }

    return true
  }

  // 自定义上传方法，确保JWT token被正确发送
  const customUpload = async (options: any) => {
    const { file, onProgress, onSuccess, onError } = options

    try {
      // 获取token
      const token = localStorage.getItem('token')
      if (!token) {
        throw new Error('未登录或token已过期')
      }

      // 创建FormData对象
      const formData = new FormData()
      formData.append('file', file)

      // 使用项目统一的request工具而不是直接使用axios
      const response = await uploadAttachment(formData)

      // 打印响应数据，用于调试

      // 确保response存在且有效
      if (response && response.code === 0) {
        // 适配不同的响应数据结构
        const fileId = response.data.id || response.data.upload_file_id || response.data.file_id
        if (fileId) {
          // 确保response.data中包含id字段
          if (!response.data.id) {
            response.data.id = fileId
          }

          // 上传成功回调 - 传递完整的响应对象
          // 这将触发handleFileUploadSuccess函数
          onSuccess(response)
        } else {
          ElMessage.error('文件上传成功但返回数据不完整')
          onError(new Error('文件上传成功但返回数据不完整'))
        }
      } else {
        // 如果上传失败，调用错误回调
        const errorMsg = response ? response.msg : '上传失败'
        onError(new Error(errorMsg))
      }
    } catch (error) {
      onError(error)
    }
  }

  // 处理文件上传成功
  const handleFileUploadSuccess = (response: any, file: any, fileList: any[]) => {
    console.log('文件上传成功回调:', response)
    console.log('上传的文件对象:', file)
    console.log('当前文件列表:', fileList)

    // 检查response是否有效，避免处理undefined的情况
    if (!response) {
      console.warn('文件上传成功回调收到undefined响应，忽略此次回调')
      return
    }

    if (response.code === 0 && response.data) {
      // 适配不同的响应数据结构
      const fileId = response.data.id || response.data.upload_file_id || response.data.file_id
      if (fileId) {
        // 保留成功上传的文件在fileList中
        console.log('文件上传成功并保留在列表中:', file.name, 'ID:', fileId)

        // 在fileList中找到当前文件并确保其response和status正确设置
        const fileIndex = fileList.findIndex(f => f.uid === file.uid)
        if (fileIndex !== -1) {
          // 创建一个新的文件对象，确保响应式更新
          const updatedFile = {
            ...fileList[fileIndex],
            // 直接设置文件ID，确保可以从file.id获取到
            id: fileId,
            response: {
              ...response,
              data: {
                ...response.data,
                id: fileId, // 确保ID字段存在且正确
              },
            },
            status: 'success',
          }

          // 替换原文件对象
          fileList[fileIndex] = updatedFile

          console.log('文件ID设置情况:', {
            'file.id': updatedFile.id,
            'response.data.id': updatedFile.response.data.id,
          })
        }

        // 立即更新uploadForm.fileList - 确保使用最新的fileList
        uploadForm.fileList = [...fileList]

        // 强制更新视图，确保文件列表正确显示
        nextTick(() => {
          console.log('上传后的文件列表:', uploadForm.fileList)
          console.log('文件列表长度:', uploadForm.fileList.length)

          // 调试文件ID提取
          if (uploadForm.fileList.length > 0) {
            const debugResult = debugAllFileIds()
          }
        })
      } else {
        ElMessage.error('文件上传成功但返回数据不完整')
      }
    } else {
      // 处理response存在但code不为0的情况
      const errorMsg = response.msg ? response.msg : '未知错误'
      ElMessage.error('文件上传失败: ' + errorMsg)
      // 移除上传失败的文件
      uploadForm.fileList = fileList.filter(f => f.uid !== file.uid)
    }
  }

  // 处理文件上传错误
  const handleFileUploadError = (error: any, file: any, fileList: any[]) => {
    console.error('文件上传错误:', error)
    ElMessage.error('文件上传失败，请重试')
    // 移除上传失败的文件
    uploadForm.fileList = fileList.filter(f => f.uid !== file.uid)
  }

  // 处理分页大小变化
  const handleSizeChange = (size: number) => {
    queryForm.limit = size
    fetchNoteList()
  }

  // 处理当前页码变化
  const handleCurrentChange = (current: number) => {
    queryForm.page = current
    fetchNoteList()
  }

  // 当前视图
  const currentView = ref('personal')

  // 当前用户ID - 这里应该从用户状态或store中获取，暂时使用默认值
  const currentUserId = ref(1) // 默认用户ID，实际应该从用户状态中获取

  // 处理视图切换
  const handleViewChange = (view: string) => {
    currentView.value = view
    // 根据不同视图重置查询参数
    if (view === 'trash') {
      queryForm.status = -1 // 回收站状态
    } else if (view === 'shared') {
      queryForm.status = 1 // 共享状态
    } else {
      queryForm.status = 0 // 个人文件状态
    }
    queryForm.page = 1
    fetchNoteList()

    // 在切换到个人文件视图时，预加载分享选项数据
    if (view === 'personal') {
      loadShareOptions()
    }
  }

  // 组件挂载时初始化
  onMounted(() => {
    fetchNoteList()
    // 预加载分享选项数据
    loadShareOptions()
  })

  // 还原笔记
  const handleRestoreNote = async (note: Note) => {
    try {
      const res = await restoreNote(note.id)

      if (res.code === 0) {
        ElMessage.success('笔记还原成功')
        fetchNoteList()
      } else {
        ElMessage.error(res.msg || '笔记还原失败')
      }
    } catch (error) {
      ElMessage.error('笔记还原失败: ' + (error as Error).message)
    }
  }

  // 彻底删除笔记
  const handleForceDeleteNote = async (note: Note) => {
    try {
      await ElMessageBox.confirm('确定要彻底删除该笔记吗？删除后将无法恢复', '彻底删除确认', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })

      const res = await forceDeleteNote(note.id)

      if (res.code === 0) {
        ElMessage.success('笔记彻底删除成功')
        fetchNoteList()
      } else {
        ElMessage.error(res.msg || '笔记彻底删除失败')
      }
    } catch (error) {
      // 用户取消删除操作时不提示错误
      if ((error as Error).message !== 'cancel') {
        ElMessage.error('笔记彻底删除失败: ' + (error as Error).message)
      }
    }
  }

  // 文件预览对话框
  const previewVisible = ref(false)
  const previewFile = ref<any>(null)
  const previewUrl = ref('')
  const textPreviewContent = ref('')
  const previewLoading = ref(false)

  // 处理预览关闭
  const handlePreviewClosed = () => {
    // 释放blob URL以避免内存泄漏
    if (previewUrl.value) {
      URL.revokeObjectURL(previewUrl.value)
      previewUrl.value = ''
    }
    // 清空文本预览内容
    textPreviewContent.value = ''
  }

  // 判断是否为图片文件
  const isImageFile = (ext: string | undefined): boolean => {
    const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']
    return imageExts.includes(ext?.toLowerCase() || '')
  }

  // 判断是否为文本文件
  const isTextFile = (ext: string | undefined): boolean => {
    const textExts = [
      'txt',
      'md',
      'json',
      'xml',
      'csv',
      'log',
      'html',
      'htm',
      'js',
      'css',
      'vue',
      'ts',
      'jsx',
      'tsx',
    ]
    return textExts.includes(ext?.toLowerCase() || '')
  }

  // 判断文件是否可预览
  const isPreviewable = (file: any): boolean => {
    // 检查文件扩展名
    const ext = file.ext || (file.name && file.name.split('.').pop()) || ''

    // PDF文件可预览
    if (ext.toLowerCase() === 'pdf') return true

    // 图片文件可预览
    if (isImageFile(ext)) return true

    // 文本文件可预览
    if (isTextFile(ext)) return true

    return false
  }

  // 处理文件预览
  const handleFilePreview = async (file: any) => {
    previewFile.value = file
    previewVisible.value = true
    previewLoading.value = true

    try {
      // 对于PDF和图片文件，使用fetch获取文件内容并创建blob URL
      if (file.ext === 'pdf' || file.ext === 'PDF' || isImageFile(file.ext)) {
        const response = await request({
          url: `/api/disk/preview-attachment?file_id=${file.id}`,
          method: 'GET',
          responseType: 'blob',
        })

        // 创建blob URL
        const blob = new Blob([response.data], { type: response.headers['content-type'] })
        previewUrl.value = URL.createObjectURL(blob)
      }
      // 对于文本文件，获取文本内容
      else if (isTextFile(file.ext)) {
        const response = await request({
          url: `/api/disk/preview-attachment?file_id=${file.id}`,
          method: 'GET',
        })

        textPreviewContent.value = response.data || '文件内容为空'
      }
    } catch (error) {
      console.error('预览文件失败:', error)
      ElMessage.error('预览文件失败，请尝试下载文件查看')
    } finally {
      previewLoading.value = false
    }
  }

  // 处理预览错误
  const handlePreviewError = () => {
    ElMessage.error('文件预览失败，请尝试下载文件查看')
  }
</script>

<style scoped>
  .disk-container {
    padding: 20px;
  }

  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .header-actions {
    display: flex;
    align-items: center;
    gap: 16px;
  }

  .header-filter {
    margin-top: 16px;
  }

  .note-content {
    margin-top: 16px;
  }

  .file-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 16px;
    margin-bottom: 20px;
  }

  .note-item {
    position: relative;
    border: 1px solid #ebeef5;
    border-radius: 8px;
    padding: 16px;
    background-color: #fff;
    transition: all 0.3s;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    height: 180px;
    display: flex;
    flex-direction: column;
  }

  .note-item:hover {
    box-shadow: 0 4px 18px 0 rgba(0, 0, 0, 0.15);
    transform: translateY(-2px);
  }

  .note-info {
    flex: 1;
    cursor: pointer;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }

  .note-title {
    font-size: 16px;
    font-weight: 600;
    color: #303133;
    margin-bottom: 8px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .note-preview {
    font-size: 14px;
    color: #606266;
    line-height: 1.5;
    flex: 1;
    overflow: hidden;
    display: -webkit-box;
    display: box;
    line-clamp: 3;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    text-overflow: ellipsis;
  }

  .note-meta {
    font-size: 12px;
    color: #909399;
    margin-top: 8px;
    display: flex;
    flex-direction: column;
    gap: 4px;
  }

  .file-actions {
    position: absolute;
    top: 8px;
    right: 8px;
    opacity: 0;
    transition: opacity 0.3s;
  }

  .note-item:hover .file-actions {
    opacity: 1;
  }

  .share-badge {
    position: absolute;
    top: 8px;
    left: 8px;
    color: #409eff;
    font-size: 16px;
  }

  .pagination-container {
    display: flex;
    justify-content: center;
    margin-top: 20px;
  }

  .loading-container,
  .empty-container {
    grid-column: 1 / -1;
    padding: 40px 0;
  }

  .rich-text-editor {
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    overflow: hidden;
  }

  .editor-toolbar {
    background-color: #f5f7fa;
    padding: 8px;
    border-bottom: 1px solid #dcdfe6;
    display: flex;
    align-items: center;
    gap: 4px;
  }

  .content-editor {
    min-height: 300px;
    padding: 12px;
    overflow-y: auto;
    outline: none;
  }

  .content-editor:focus {
    border-color: #409eff;
  }

  .attachment-list {
    margin-top: 16px;
  }

  .attachment-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 0;
    border-bottom: 1px solid #f0f0f0;
  }

  .attachment-item:last-child {
    border-bottom: none;
  }

  .attachment-info {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .attachment-name {
    font-size: 14px;
    color: #303133;
  }

  .attachment-size {
    font-size: 12px;
    color: #909399;
  }

  .attachment-actions {
    display: flex;
    gap: 8px;
  }

  .preview-dialog {
    text-align: center;
  }

  .preview-image {
    max-width: 100%;
    max-height: 70vh;
  }

  .preview-pdf {
    width: 100%;
    height: 70vh;
  }

  .preview-text {
    text-align: left;
    padding: 16px;
    background-color: #f5f7fa;
    border-radius: 4px;
    max-height: 70vh;
    overflow-y: auto;
    white-space: pre-wrap;
    font-family: monospace;
  }
</style>
